package com.google.code.toub.waves.editor.annotation;

import java.util.List;

import com.google.code.toub.waves.editor.util.BlipEditor;
import com.google.wave.api.Annotation;
import com.google.wave.api.Blip;
import com.google.wave.api.BlipContentRefs;

public class ExtendedAnnotation {
	/**
	 * Annotation key
	 */
	private final String baseKey;

	private final String valueKey;

	private final String labelKey;

	private final BlipEditor blipEditor = new BlipEditor();

	private final String labelFormat;

	private final AnnotationColor labelColor;

	public ExtendedAnnotation(String applicationKey, String annotationKey,
			String labelFormat, AnnotationColor labelColor) {
		super();
		this.baseKey = applicationKey + "/" + annotationKey;
		this.valueKey = baseKey + ".value";
		this.labelKey = baseKey + ".label";
		if (labelFormat == null) {
			this.labelFormat = "[" + annotationKey + ": %1$s]";
		} else {
			this.labelFormat = labelFormat;
		}
		this.labelColor = labelColor;
	}

	public ExtendedAnnotation(String applicationKey, String annotationKey) {
		this(applicationKey, annotationKey, null, null);
	}

	public ExtendedAnnotation(String applicationKey, String annotationKey,
			String labelFormat) {
		this(applicationKey, annotationKey, labelFormat, null);
	}

	public ExtendedAnnotation(String applicationKey, String annotationKey,
			AnnotationColor labelColor) {
		this(applicationKey, annotationKey, null, labelColor);
	}

	/**
	 * Update annotation value and label
	 * 
	 * @param blip
	 * @param value
	 */
	public void update(Blip blip, String value) {
		if (blip != null) {
			clear(blip);
			add(blip, value);
		}
	}

	/**
	 * Add annotation value and label.
	 * 
	 * @param blip
	 * @param value
	 */
	private void add(Blip blip, String value) {
		addValue(blip, value);
		addLabel(blip, value);
	}

	/**
	 * Add annotation value.
	 * 
	 * @param blip
	 * @param value
	 */
	private void addValue(Blip blip, String value) {
		if (blip != null) {
			blip.all().annotate(valueKey, value);
		}
	}

	/**
	 * Add annotation label.
	 * 
	 * @param blip
	 * @param value
	 */
	private void addLabel(Blip blip, String value) {
		blipEditor.append(blip, String.format(labelFormat, value), labelColor,
				labelKey);
	}

	/**
	 * Clear annotation (label and value)
	 * 
	 * @param blip
	 */
	public void clear(Blip blip) {
		if (blip != null) {
			clearValue(blip);

			clearLabel(blip);
		}
	}

	/**
	 * Clear annotation value.
	 * 
	 * @param blip
	 */
	private void clearValue(Blip blip) {
		blip.all().clearAnnotation(valueKey);
	}

	/**
	 * Clear annotation label.
	 * 
	 * @param blip
	 */
	private void clearLabel(Blip blip) {
		if (blip.getAnnotations() != null) {
			// remove previous expiration labels
			List<Annotation> annotationList = blip.getAnnotations().get(
					labelKey);
			if (annotationList != null) {
				for (Annotation annotation : annotationList) {
					BlipContentRefs blipRange = blip.range(annotation
							.getRange().getStart(), annotation.getRange()
							.getEnd());
					// remove old expiration date text
					// FIXME replace by a space because delete fails
					// with a ConcurrentModificationException
					blipRange.replace("\n");
				}
			}
		}
	}

}
